//
//  GSLinkedIn.m
//  AgileNYC
//
//  Created by German on 28.06.14.
//  Copyright (c) 2014 Softlegion. All rights reserved.
//

#import "GSLinkedIn.h"
#import "SGSServerManagerConsts.h"
#import "SGSUtils.h"

typedef void(^GSCompletionBlock)(BOOL isSuccess, NSError * error, NSInteger statusCode);

@interface GSLinkedIn () <UIWebViewDelegate>

@property (copy, nonatomic) GSCompletionBlock loginCompletionBlock;
@property (strong, nonatomic) NSString * currentToken;
@property (strong, nonatomic) NSString * redirectHost;
@property (strong, nonatomic) UIActivityIndicatorView * spinner;
@property (strong, nonatomic) UIWebView * loginDialogWebView;

@end


@implementation GSLinkedIn

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.currentToken = nil;
        self.redirectHost = [[NSURL URLWithString:linkedInRedirectURL] host];
    }
    return self;
}

-(void) connectToLinkedIn:(NSInteger) reserved
                onSuccess:(void(^)(void)) success
                onFailure:(void(^)(NSError * error, NSInteger statusCode)) failure {
    [self getLinkedInAuthorizationCode:reserved
             onSuccess:^(NSString *authCode) {
                [self loginWithLinkedIn:authCode
                              onSuccess:^(NSDictionary *response) {
                                  self.currentToken = [response valueForKey:linkedInTokenKey];
                                  if (success) {
                                      success();
                                  }
                              } onFailure:^(NSError *error, NSInteger statusCode) {
                                  if (failure) {
                                      failure(error,statusCode);
                                  }
                              }];
                 
             } onFailure:^(NSError *error, NSInteger statusCode) {
                 if (failure) {
                     failure(error,statusCode);
                 }
             }];
}

- (void)requestUserInfo:(int) reserved
              onSuccess:(void(^)(NSDictionary * userInfo)) success
              onFailure:(void(^)(NSError * error)) failure {
    
    __block NSMutableDictionary * dictOfUser = nil;
    
    [self getUserFromLinkedIn:self.currentToken
                    onSuccess:^(NSDictionary *response) {
                        dictOfUser = [NSMutableDictionary dictionaryWithDictionary:response];
                        
                        [self getAdditionalUserInfoFromLinkedIn:self.currentToken
                              onSuccess:^(NSDictionary *response) {
                                  [dictOfUser addEntriesFromDictionary:response];
                                  if (success) {
                                      success(dictOfUser);
                                  }
                              }
                              onFailure:^(NSError *error, NSInteger statusCode) {
                                  if (success) {
                                      success(dictOfUser);
                                  }
                              }];
                        
                    } onFailure:^(NSError *error, NSInteger statusCode) {
                        if (failure) {
                            failure(error);
                        }
                    }];
}


- (void)requestUserInfoWithImageHeight:(NSInteger) height
                                 Width:(NSInteger) width
                             onSuccess:(void(^)(NSDictionary * userInfo)) success
                       onImageReceived:(void(^)(NSData* userImage)) imageReceived
                             onFailure:(void(^)(NSError * error)) failure {
    [self requestUserInfo:0
                onSuccess:^(NSDictionary *userInfo) {
                    [self getUserImageFromLinkedIn:0
                                         onSuccess:^(NSData *userImage) {
                                             if (imageReceived) {
                                                 imageReceived(userImage);
                                             }
                                         }
                                         onFailure:^(NSError *error) {
                                             if (imageReceived) {
                                                 imageReceived(nil);
                                             }
                                         }];
                    if (success) {
                        success(userInfo);
                    }
                } onFailure:^(NSError *error) {
                    if (failure) {
                        failure(error);
                    }
                }];
    
}


-(void) getLinkedInAuthorizationCode:(NSInteger) reserved
                           onSuccess:(void(^)(NSString * authCode)) success
                           onFailure:(void(^)(NSError * error, NSInteger statusCode)) failure
{
    __weak __typeof(self)weakSelf = self;
    
    self.loginCompletionBlock = ^(BOOL isSuccess, NSError * error, NSInteger statusCode) {
        if (isSuccess) {
            if (success) {
                success(weakSelf.currentToken);
            }
        } else {
            if (failure) {
                failure(error, 0);
            }
        }
    };
    
    NSString * urlString = [NSString stringWithFormat:
                            @"https://www.linkedin.com/uas/oauth2/authorization?"
                            "response_type=%@"
                            "&client_id=%@"
                            "&scope=%@"
                            "&state=%@"
                            "&redirect_uri=%@"
                            ,@"code"
                            ,linkedInAppId
                            ,@"r_fullprofile r_emailaddress r_contactinfo"
                            ,linkedInStateString
                            ,linkedInRedirectURL];
    
    
    //self.currentAuthHost = [[NSURL URLWithString:linkedInRedirectURL] host];
    //self.currentTokenKey = linkedInCodeKey;
    //self.currentExpiredKey = linkedInExpiredKey;
    //self.currentUserIDKey = linkedInUserIdKey;
    //self.currentErrorKey = linkedInErrorKey;
    
    NSString* webUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    NSLog(@"LinkedIn AuthCode: %@", webUrlString);
    
    [self showExternalLoginDialogWithURL:webUrlString caption:@"Login to LinkedIn"];
}

-(void) loginWithLinkedIn:(NSString*) authCode
                onSuccess:(void(^)(NSDictionary * response)) success
                onFailure:(void(^)(NSError * error, NSInteger statusCode)) failure
{
    
    NSString * urlString = [NSString stringWithFormat:
                            @"https://www.linkedin.com/uas/oauth2/accessToken?"
                            "grant_type=%@"
                            "&code=%@"
                            "&client_id=%@"
                            "&client_secret=%@"
                            "&redirect_uri=%@"
                            
                            ,@"authorization_code"
                            ,authCode
                            ,linkedInAppId
                            ,linkedInSecret
                            ,linkedInRedirectURL];
    
    
    //self.currentAuthHost = [[NSURL URLWithString:linkedInRedirectURL] host];
    //self.currentTokenKey = linkedInTokenKey;
    //self.currentExpiredKey = linkedInExpiredKey;
    //self.currentUserIDKey = linkedInUserIdKey;
    //self.currentErrorKey = linkedInErrorKey;
    
    NSString* webUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    [self makeRequestToURL:webUrlString
                      type:@"POST"
                 onSuccess:^(NSDictionary *dict) {
                     if (success) {
                         success(dict);
                     }
                 }
                 onFailure:^(NSError *error, NSInteger statusCode) {
                     if (failure) {
                         failure(error, statusCode);
                     }
                 }];
    
}


-(void) getUserFromLinkedIn:(NSString*) userToken
                  onSuccess:(void(^)(NSDictionary * response)) success
                  onFailure:(void(^)(NSError * error, NSInteger statusCode)) failure
{
    
    NSString * urlString = [NSString stringWithFormat:@"%@%@%@%@",
                            linkedInURL,
                            @"people/~?oauth2_access_token=",
                            userToken,
                            @"&format=json"];

    NSString * webUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    [self makeRequestToURL:webUrlString
                      type:@"GET"
                 onSuccess:^(NSDictionary *dict) {
                     if (success) {
                         success(dict);
                     }
                 }
                 onFailure:^(NSError *error, NSInteger statusCode) {
                     if (failure) {
                         failure(error, statusCode);
                     }
                 }];
}

-(void) getAdditionalUserInfoFromLinkedIn:(NSString*) userToken
                                onSuccess:(void(^)(NSDictionary * response)) success
                                onFailure:(void(^)(NSError * error, NSInteger statusCode)) failure
{
    
    /*NSURL *url = [NSURL URLWithString:@"http://api.linkedin.com/v1/people/~:(id,first-name,last-name,industry,picture-url,location:(name),positions:(company:(name),title),specialties,date-of-birth,interests,languages)"];*/
    
    NSString * urlString = [NSString stringWithFormat:@"%@%@%@%@%@%@",
                            linkedInURL,
                            @"people/~",
                            @":(id,location:(name),phone-numbers,public-profile-url)",
                            @"?oauth2_access_token=",
                            userToken,
                            @"&format=json"];
    
    NSString * webUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    [self makeRequestToURL:webUrlString
                      type:@"GET"
                 onSuccess:^(NSDictionary *dict) {
                     if (success) {
                         success(dict);
                     }
                 }
                 onFailure:^(NSError *error, NSInteger statusCode) {
                     if (failure) {
                         failure(error, statusCode);
                     }
                 }];
}

-(void) getUserImageFromLinkedIn:(int) reserved
                       onSuccess:(void(^)(NSData * userImage)) success
                       onFailure:(void(^)(NSError * error)) failure
{
    
    NSString * urlString = [NSString stringWithFormat:@"%@%@%@%@%@%@",
                            linkedInURL,
                            @"people/~",
                            @":(picture-url)",
                            @"?oauth2_access_token=",
                            self.currentToken,
                            @"&format=json"];
    
    NSString * webUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    [self makeRequestToURL:webUrlString
                      type:@"GET"
                 onSuccess:^(NSDictionary *dict) {
                     NSString * imageURL = [dict objectForKey:@"pictureUrl"];
                     
                     dispatch_queue_t backgroundQueue =
                     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
                     
                     dispatch_async(backgroundQueue, ^{
                         NSData *avatarData = nil;
                         NSString *imageURLString = imageURL;
                         if (imageURLString) {
                             NSURL *imageURL = [NSURL URLWithString:imageURLString];
                             avatarData = [NSData dataWithContentsOfURL:imageURL];
                         }
                         
                         if (avatarData) {
                             // Update UI from the main thread when available
                             dispatch_async(dispatch_get_main_queue(), ^{
                                 //self.userAvatar.image = [UIImage imageWithData:avatarData];
                                 if (success) {
                                     success(avatarData);
                                 }
                             });
                         } else {
                             if (success) {
                                 success(nil);
                             }
                         }
                     });
                 }
                 onFailure:^(NSError *error, NSInteger statusCode) {
                     if (failure) {
                         failure(error);
                     }
                 }];
}


-(void) showExternalLoginDialogWithURL:(NSString*) urlString caption:(NSString*) caption {
    UIViewController * mainVC = [UIApplication sharedApplication].keyWindow.rootViewController;
    UIViewController * vc = [[UIViewController alloc] init];
    UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:vc];
    self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    
    CGRect rect = mainVC.view.bounds;
    rect.origin = CGPointZero;
    
    UIWebView * webView = [[UIWebView alloc] initWithFrame:rect];
    self.loginDialogWebView = webView;
    
    webView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    webView.delegate = self;
    
    [vc.view addSubview:webView];
    vc.navigationItem.title = caption;
    
    UIBarButtonItem * cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(onCancelLoginButtonClick:)];
    UIBarButtonItem * activityButton = [[UIBarButtonItem alloc] initWithCustomView:self.spinner];
    [vc.navigationItem setRightBarButtonItem:cancelButton];
    [vc.navigationItem setLeftBarButtonItem:activityButton];
    
    [mainVC presentViewController:nav animated:YES completion:nil];
    
    NSURL * url = [NSURL URLWithString:urlString];
    NSURLRequest * urlRequest = [NSURLRequest requestWithURL:url];
    
    [webView loadRequest:urlRequest];
}

-(void) hideExternalLoginDialog {
    UIViewController * mainVC = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    self.loginDialogWebView.delegate = nil;
    
    [self.spinner stopAnimating];
    
    self.spinner = nil;
    
    [mainVC dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - NSMutableURLRequest

-(void) makeRequestToURL:(NSString*) urlString
                    type:(NSString*) requestType
               onSuccess:(void(^)(NSDictionary * dict)) success
               onFailure:(void(^)(NSError * error, NSInteger statusCode)) failure
{
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:requestType];
    
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        
        if ([data length] >0 && connectionError == nil)
        {
            NSError * e;
            NSDictionary * result =
            [NSJSONSerialization JSONObjectWithData: data
                                            options: NSJSONReadingMutableContainers
                                              error: &e];
            if (success) {
                success(result);
            }
        }
        else if ([data length] == 0 && connectionError == nil)
        {
            if (success) {
                success(nil);
            }
        }
        else if (connectionError != nil){
            if (failure) {
                failure(connectionError,0);
            }
        }
    }];
}

-(void) onCancelLoginButtonClick:(id) sender {
    [self hideExternalLoginDialog];
}

#pragma mark - UIWebViewDelegate

// Отлавливаем URL с токенами
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    
    GSLog(GSLogInfo, @"%@", [request URL]);
    GSLog(GSLogInfo, @"Current HOST: %@", [[request URL] host]);
    GSLog(GSLogInfo, @"Auth host: %@", self.redirectHost);
    
    NSError * error = nil;
    BOOL isSuccess = [[[request URL] host] isEqualToString:self.redirectHost];
    
    if (isSuccess) {
        
        NSString * query = [[request URL] query];
        
        if (query==nil) {
            query = [[request URL] absoluteString] ;
        }
        
        NSArray * array = [query componentsSeparatedByString:@"#"];
        
        if ([array count]>1) {
            query = [array lastObject];
        }
        
        NSArray * pairs = [query componentsSeparatedByString:@"&"];
        
        for (NSString * pair in pairs) {
            NSArray * keyAndValues = [pair componentsSeparatedByString:@"="];
            
            if ([keyAndValues count] >1) {
                
                NSString * key = [keyAndValues firstObject];
                
                /*if ([key isEqualToString:self.currentTokenKey]) {
                    self.currentToken.token = [[keyAndValues lastObject] copy];
                } else if ([key isEqualToString:self.currentExpiredKey]) {
                    NSTimeInterval interval = [[keyAndValues lastObject] doubleValue];
                    self.currentToken.expiration = [NSDate dateWithTimeIntervalSinceNow:interval];
                } else if ([key isEqualToString:self.currentUserIDKey]) {
                    self.currentToken.userID = [keyAndValues lastObject];
                } else if ([key isEqualToString:self.currentErrorKey]) {
                    error = [[NSError alloc] initWithDomain:[keyAndValues lastObject] code:0 userInfo:nil];
                    isSuccess = NO;
                }*/
                
                if ([key isEqualToString:linkedInCodeKey]) {
                    self.currentToken = [[keyAndValues lastObject] copy];
                } else if ([key isEqualToString:linkedInErrorKey]) {
                    error = [[NSError alloc] initWithDomain:[keyAndValues lastObject] code:0 userInfo:nil];
                    isSuccess = NO;
                }
            }
        }
        
        [self hideExternalLoginDialog];
    }
    
    if (self.loginCompletionBlock) {
        self.loginCompletionBlock(isSuccess,error,0);
    }
    
    return !isSuccess;
}

- (void)webViewDidStartLoad:(UIWebView *)webView {
    [self.spinner startAnimating];
}

- (void)webViewDidFinishLoad {
    [self.spinner stopAnimating];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    [self.spinner stopAnimating];
}


@end
